﻿/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/

using System;
using System.Numerics;

namespace CSharpKit.Numerics.LinearAlgebra.Factorization
{
    /// <summary>
    /// QR - 正交分解 <br/>
    /// </summary>
    /// <remarks>
    /// 定理：设矩阵A∈R(m x n)，且非奇异，则一定存在正交矩阵Q、上三角矩阵R，使得 A = QR <para/>
    /// The computation of the QR decomposition is done at construction time by Householder transformation. <br/>
    /// [1] <seealso cref="QRMethod.Full"/>：the resulting Q matrix is an m x m matrix and the R matrix is an m x n matrix. <br/>
    /// [2] <seealso cref="QRMethod.Thin"/>：the resulting Q matrix is an m x n matrix and the R matrix is an n x n matrix. <br/>
    /// </remarks>
    /// <typeparam name="T">Supported data types are double, single, <see cref="Complex"/>.</typeparam>
    public abstract class QR<T> : ISolver<T>
        where T : struct, IFormattable, IEquatable<T>
    {
        protected QR(Matrix<T> q, Matrix<T> rFull, QRMethod method)
        {
            Q = q;
            FullR = rFull;
            Method = method;

            _lazyR = new Lazy<Matrix<T>>(FullR.UpperTriangle);
        }



        readonly Lazy<Matrix<T>> _lazyR;

        protected readonly Matrix<T> FullR;
        protected readonly QRMethod Method;


        /// <summary>
        /// Gets or sets orthogonal Q matrix
        /// </summary>
        public Matrix<T> Q { get; private set; }

        /// <summary>
        /// Gets the upper triangular factor R.
        /// </summary>
        public Matrix<T> R => _lazyR.Value;


        public abstract T Determinant { get; }
        public abstract bool IsFullRank { get; }





        #region ISolver<T>

        public Matrix<T> Solve(Matrix<T> input)
        {
            var x = Matrix<T>.Builder.SameAs(input, FullR.ColumnCount, input.ColumnCount, fullyMutable: true);
            Solve(input, x);
            return x;
        }
        public abstract void Solve(Matrix<T> input, Matrix<T> result);

        public Vector<T> Solve(Vector<T> input)
        {
            var x = Vector<T>.Builder.SameAs(input, FullR.ColumnCount);
            Solve(input, x);
            return x;
        }
        public abstract void Solve(Vector<T> input, Vector<T> result);

        #endregion


        //}}@@@
    }


}

